基于Java对于MongoDB数据库的复杂查询操作

前言

在sql转noSql途中总是免不了一些对于原有的复杂sql语句的转译工作,因为不熟悉java环境下对于mongoDB操作的语句,所以走了不少的弯路,这些复杂语句在stackoverflow中找又会花上不少时间,于是在这里做个记录。

Java的配置并且连接MongoDB

  • 首先在pom.xml文件中加入依赖包: "mongo-java-driver"(因为scala对于java的支持,所以这个driver就不作区分了),配置的代码如下:
      <dependency>
        <groupId>org.mongodb</groupId>
        <artifactId>mongo-java-driver</artifactId>
        <version>3.4.2</version>
      </dependency>
    
  • 连接Mongo Server以及collection的方法
    • org.mongodb中提供了ServerAddress类用来储存连接mongo的ip地址以及端口,初始化的方法为:
      private ServerAddress serverAddress = new ServerAddress("<ip地址>", "<端口>(这是个int)");
      
    • 如果这个MongoDB的服务器是一个集群,那么通常来说需要设置setSlaveOK才能通过某一台服务器去访问数据,但是,我们可以把整个集群的服务器list输入给ServerAddress类,其初始化的方法为:
      private MongoClient mongoClient = new MongoClient(Arrays.asList(new ServerAddress("<ip地址1>", "<端口>(这是个int)"),
                                                                      new ServerAddress("<ip地址2>", "<端口>(这是个int)"),
                                                                      new ServerAddress("<ip地址3>", "<端口>(这是个int)")));
      
    • 如果这个mongoDB的数据库是有权限访问设置的数据库,则还需要MongoCredential类将数据库的 名称,用户名,密码传入连接数据库的方法中,其初始化的方法为:
      private MongoCredential credential = MongoCredential.createCredential("<用户名>", "<数据库名称>", "<密码>");
      
    • 最后才是连接MongoDB数据库的操作,使用的是MongoClient类,其初始化的方法为:(注意这里的credential变量需要转化为List类才能作为输入)
      private MongoClient mongoClient = new MongoClient(serverAddress, Arrays.asList(credential));
      
    • 如若要获取这个server下的某一个数据库(Database),则需要执行如下方法:
      MongoDatabase mydb = mongoClient.getDatabase("<数据库名称>");
      
    • 在mongoDB中,我们熟知的table被称为collection,所以如果要获得某个collection(表格),需要执行如下的方法:
      MongoCollection myCollection = mydb.getCollection("<该数据库下collection的名字>");
      
    至此,我们已经可以连接到MongoDB下的所有数据表格,下面就可以来看看基于java对于MongoDB的复杂语句操作了。

基于Java对于MongoDB数据库的复杂语句查询

  • 基础准备
    • 在对MongoDB执行复杂查询之前,我们先要了解一下在Mongo-Java-Driver中是如何储存查询结果的。其用于储存结果的类是MongoCursor, 其通过collection类的find方法获取查询结果并通过.iterator()方法返回该MongoCursor类,本质是一个类似于Iterator的对象,可以通过调用hasNext()next()方法来遍历整个返回结果。
    • 另一方面,MongoCursor中所储存的数据类型为Document,类似于Json的存储方式,可以通过google的Gson包将其映射为你想要的java对象,实现方式为:
      private Gson gson = new Gson();
      // 转换为对象
      gson.fromJson(gson.toJson(<你所获得的Document对象>), <你需要转换的成为的对象>.class)
      
  • Java对MongoDB的复杂语句查询操作
    这里为了保证对sql选手亲和度(我本人也是从sql起步的),我会尽量把这里的一些查询翻译成sql中比较相似的操作。
    • where分句

      • 常用的判别符号
        基于Java的MongoDB的查询语句如果需要指定where的条件,需要用到BasicDBObject类用于存储where分句中判别字段(列的名称),判别类型(等于,不等于,大于,小于)和用于判别的值。其基本的初始化方法为:

        BasicDBObject dbObject = new BasicDBObject("<判别类型>", "用于判别的值");
        // 指定判别的字段
        BasicDBObject identification = new BasicDBObject("<用于判别的字段(列的名字)>", dbObject)
        // Example: 取得大于等于某个时间点的所有数据库记录
        BasicDBObject exObject = new BasicDBObject("time", new BasicDBObject("$gte", (from + " 00:00")))
        

        常用判别符号有:

        判别符号 意义
        $eq 相等
        $ne 不等于
        $gte 大于等于
        $gt 大于
        $lte 小于等于
        $lt 小于
      • 在where分句中使用and和or等逻辑关联词
        从上面的叙述中可以看到,我们可以用BasicDBObject对象来表示对某个字段(某列)做限制条件的查找。如果要将这些查询条件使用逻辑关联词连在一起,则我们需要使用List对象将这些要关联的条件语句(BasicDBObject对象)连接在一起,再在最外层用一个新的BasicDBObject对象封装这些用逻辑连词连在一起的BasicDBObject List。具体实现代码如下:

        // 使用List来连接需要用逻辑关联词串联起来的条件语句
        List<DBObject> criteria = new ArrayList<>();
        criteria.add(new BasicDBObject("time", new BasicDBObject("$gte", (from + " 00:00"))));
        criteria.add(new BasicDBObject("time", new BasicDBObject("$lte", (to + " 23:59"))));
        criteria.add(new BasicDBObject("idc_group", idcGroup));
        // 使用and来连接这个list
        // 这里也可以使用"$or"字段表示"或"逻辑
        BasicObject andConnection =new BasicDBObject("$and", criteria);
        // 之后使用find方法去找到符合这个where条件的记录。
        MongoCursor<Document> tCursor = mydb.getCollection(table).find(new BasicDBObject("$and", criteria)).iterator();
        
    • 聚合操作(Aggregation, Group By)
      基于Java对于MongoDB数据库查询如果需要执行聚合操作,则需要从MongoCollection对象调用aggregate方法,并把所需要的条件串联为list并作为输入进入aggregate方法。常用的一些关键词有:

      关键词 意义
      $match 相等,类似于where中的等于某值
      $sort 排序
      $limit 与mysql中的limit相同

      具体的关键词操作请参照文档 http://www.runoob.com/mongodb/mongodb-aggregate.html
      下面给出例子:

      // 目标:获取所有满足如下条件的数据:
      // 1. "date"字段满足某个值
      // 2. 先通过orderName1降序,再通过orderName2降序
      // 3. 获取的记录不超过10条
      MongoCursor<Document> cursor = quality.aggregate(Arrays.asList(
        // "$match"用于筛选date匹配这个值的记录
        new Document("$match", new Document("date", (int)(Integer.valueOf(timeInput[0] + timeInput[1] + timeInput[2])))),    
        new BasicDBObject("$sort", new BasicDBObject(orderName1, -1)),
        new BasicDBObject("$sort", new BasicDBObject(orderName2, -1)),
        new BasicDBObject("$limit", 10)
      )).iterator();
      
    • 值得一提的是,因为MongoDB自身数据结构存储方式的问题,其不支持对于两个collection进行join的操作。

至此,基于Java对MongoDB数据库的查询的复杂操作已经基本涵盖,希望可以帮助到各位。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,458评论 4 363
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,454评论 1 294
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 109,171评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,062评论 0 207
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,440评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,661评论 1 219
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,906评论 2 313
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,609评论 0 200
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,379评论 1 246
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,600评论 2 246
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,085评论 1 261
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,409评论 2 254
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,072评论 3 237
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,088评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,860评论 0 195
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,704评论 2 276
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,608评论 2 270

推荐阅读更多精彩内容

  • 1. Java基础部分 基础部分的顺序:基本语法,类相关的语法,内部类的语法,继承相关的语法,异常的语法,线程的语...
    子非鱼_t_阅读 31,296评论 18 399
  • 这部分主要是开源Java EE框架方面的内容,包括Hibernate、MyBatis、Spring、Spring ...
    杂货铺老板阅读 1,270评论 0 2
  • 第一次使用简书 希望大家以后多多指教 喜欢的两个球星,附上一张我科的图片 我科 附上我黑格林的图(有多少人讨厌就有...
    BWWWWB阅读 196评论 3 0
  • 公元前一百七十年,匈奴单于率十万大军犯吾边境,玉门关告急。汉文帝发檄文征告天下,一时间风云际会,英雄辈出,群龙啸聚...
    范三石阅读 1,992评论 0 1
  • 致亲爱的快乐狗耳山户外群的伙伴们: 在这秋高气爽,收获丰收的美好季节,我们迎来了快乐狗耳山户外群成立一周年的喜庆日...
    朱金玲阅读 265评论 0 0